namespace SimpleWebServices.Web.UI.Html.Validation
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using SimpleWebServices;
    using SimpleWebServices.Data;
    using SimpleWebServices.Web.UI.Html.Elements;
    using Xunit;

    public sealed class ValidatorFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<Validator>()
                .DerivesFrom<object>()
                .IsAbstractBaseClass()
                .Implements<IValidate>()
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new ValidatorDerived() as Validator);
        }

        [Fact]
        public void ctor_IInnerElements()
        {
            Assert.NotNull(new ValidatorDerived(new Label()) as Validator);
        }

        [Fact]
        public void ctor_IInnerElementsNull()
        {
            Assert.NotNull(new ValidatorDerived(null as IInnerElements) as Validator);
        }

        [Fact]
        public void prop_Display()
        {
            Assert.True(new PropertyExpectations(typeof(ValidatorDerived).GetProperty("Display"))
                .IsAutoProperty<IInnerElements>()
                .Result);
        }

        [Fact]
        public void prop_Errors()
        {
            Assert.True(new PropertyExpectations(typeof(ValidatorDerived).GetProperty("Errors"))
                .TypeIs<IList<IError>>()
                .DefaultValueIsNotNull()
                .Result);
        }

        [Fact]
        public void prop_ErrorText()
        {
            Assert.True(new PropertyExpectations(typeof(ValidatorDerived).GetProperty("ErrorText"))
                .TypeIs<string>()
                .DefaultValueIsNotNull()
                .Set(null)
                .Set(string.Empty)
                .Set("Error text to be displayed")
                .Result);
        }

        [Fact]
        public void op_Configure_Form_DataCollection()
        {
            DataCollection data = new DataCollection();
            data.Add("Display", "display");
            data.Add("ErrorText", "error");

            Label label = new Label { Id = "display" };
            Form form = new Form
            {
                Elements = { label }
            };

            Validator obj = new ValidatorDerived();
            obj.Configure(form, data);

            Assert.Same(label, obj.Display);
            Assert.Equal<string>("error", obj.ErrorText);
        }

        [Fact]
        public void op_Configure_FormInvalidDisplay_DataCollection()
        {
            DataCollection data = new DataCollection();
            data.Add("Display", "display");

            Form form = new Form
            {
                Elements =
                {
                    new TextInput { Id = "display" }
                }
            };

            Assert.Throws<ConfigurationErrorsException>(() => (new ValidatorDerived() as Validator).Configure(form, data));
        }

        [Fact]
        public void op_Configure_FormNull_DataCollection()
        {
            DataCollection data = new DataCollection();
            data.Add("Display", "display");

            Assert.Throws<ArgumentNullException>(() => (new ValidatorDerived() as Validator).Configure(null as Form, data));
        }

        [Fact]
        public void op_Configure_Form_DataCollectionEmpty()
        {
            Validator obj = new ValidatorDerived();
            obj.Configure(new Form(), new DataCollection());

            Assert.Null(obj.Display);
            Assert.Equal<string>("The information is not valid.", obj.ErrorText);
        }

        [Fact]
        public void op_Configure_Form_DataCollectionNull()
        {
            (new ValidatorDerived() as Validator).Configure(new Form(), null as DataCollection);
        }

        [Fact]
        public void op_DisplayErrors()
        {
            Label label = new Label { Id = "display" };
            Form form = new Form
            {
                Elements = { label }
            };

            ValidatorDerived obj = new ValidatorDerived(label);
            obj.Errors.Add(new Error("description"));
            obj.DisplayErrors();

            Assert.Same(label, obj.Display);
        }

        [Fact]
        public void op_SetDisplay_Form_Name()
        {
            Label label = new Label { Id = "display" };
            Form form = new Form
            {
                Elements = { label }
            };

            ValidatorDerived obj = new ValidatorDerived();
            obj.SetDisplay(form, "display");

            Assert.Same(label, obj.Display);
        }

        [Fact]
        public void op_SetDisplay_FormInvalidDisplay_Name()
        {
            Form form = new Form();
            form.Elements.Add(new TextInput { Id = "display" });

            Assert.Throws<ConfigurationErrorsException>(() => new ValidatorDerived().SetDisplay(form, "display"));
        }

        [Fact]
        public void op_SetDisplay_Form_NameMissing()
        {
            Assert.Throws<ConfigurationErrorsException>(() => new ValidatorDerived().SetDisplay(new Form(), "missing"));
        }

        [Fact]
        public void op_SetDisplay_Form_NameNull()
        {
            Assert.Throws<ArgumentNullException>(() => new ValidatorDerived().SetDisplay(new Form(), null as Name));
        }

        [Fact]
        public void op_SetDisplay_FormNull_Name()
        {
            Assert.Throws<ArgumentNullException>(() => new ValidatorDerived().SetDisplay(null as Form, "display"));
        }

        [Fact]
        public void op_Validate_IElement()
        {
            Assert.Throws<NotSupportedException>(() => (new ValidatorDerived() as Validator).Validate(null as IElement));
        }
    }
}